﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using AutoUnitTestEngine.DbAccess;
using AutoUnitTestEngine.Helpers;
using AutoUnitTestEngine.ValObjs;

namespace AutoUnitTestEngine.TestModels
{
    public abstract class BaseTestByExcel
    {
        protected const string FN_SOURCE_DATA = "SourceData",MD_ACTUAL_DATA="ActualData",
                               FN_EXPECT_DATA = "ExpectData",FN_FAIL_REPORT="FailReport",
                               FN_DIFFERENT_DATA = "DifferentData";

        protected BaseTestByExcel()
        {
            string appPath = AppDomain.CurrentDomain.BaseDirectory;
            m_TestCaseDirPath = appPath + "TestCases\\UpdateStuInfo";
        }

        protected List<DbTableParamInfo> m_SourceDbTableParams,m_ExpectDbTableParams;

        public int CaseTotalAmount { get; set; }

        protected string m_TestCaseDirPath;

        private void InitDbTableData(string dbTableName, BaseDataAccess acc, DataTable dtData)
        {
            acc.ExecSql("Truncate Table " + dbTableName + ";",false);
            var sbInitSqls = new StringBuilder();
            foreach (DataRow row in dtData.Rows)
            {
                var sbColsSql = new StringBuilder();
                var sbValsSql = new StringBuilder();

                foreach (DataColumn col in dtData.Columns)
                {
                    string colVal = Convert.ToString(row[col.ColumnName]);
                    if (sbColsSql.Length > 0) sbColsSql.Append(",");
                    sbColsSql.Append(col.ColumnName);
                    if (sbValsSql.Length > 0) sbValsSql.Append(",");
                    sbValsSql.Append("'" + colVal + "'");
                }

                sbInitSqls.Append("Insert into " + dbTableName + " (");
                sbInitSqls.Append(sbColsSql);
                sbInitSqls.Append(") values (");
                sbInitSqls.Append(sbValsSql);
                sbInitSqls.Append(");");
            }
            acc.ExecSql(sbInitSqls.ToString());
        }

        protected void InitSourceData(ExcelHelper excelHlp)
        {
            foreach (var paramInfo in m_SourceDbTableParams)
            {
                DataTable dt = excelHlp.GetDataTableFromExcel(paramInfo.TableName);
                InitDbTableData(paramInfo.TableName, paramInfo.DataAcc, dt);
            }
        }

        protected DataTable GetExpectInnerTableData(DbTableParamInfo paramInfo,ExcelHelper hlpExcel)
        {
            return hlpExcel.GetDataTableFromExcel(paramInfo.TableName);
        }

        protected List<DataTable> m_DifferentDataTables;

        protected void CompareExpectDatas(string caseDirPath)
        {
            var hlpDataCompare = new DataCompareHelper();
            string expectExcelFilePath = caseDirPath + "\\" + FN_EXPECT_DATA + ".xls";
            if(File.Exists(expectExcelFilePath))
            {
                var hlpExcel = new ExcelHelper(expectExcelFilePath);
                foreach(var paramInfo in m_ExpectDbTableParams)
                {
                    var expectData = GetExpectInnerTableData(paramInfo, hlpExcel);
                    var actualData = paramInfo.DataAcc.GetDataTable(SqlBuilder.CreateSingleTableQueryString(paramInfo.TableName,expectData.Columns,null));
                    actualData.TableName = expectData.TableName = paramInfo.TableName;
                    var compareResult = hlpDataCompare.CompareTableEachRowIsEquals(expectData, FN_EXPECT_DATA + "【" + expectData.TableName + "】",
                                                                                   actualData, MD_ACTUAL_DATA + "【" + actualData.TableName + "】",
                                                                                   paramInfo.KeyForCompareColNames,
                                                                                   paramInfo.NotCompareColNames);
                    compareResult.TableName = "DiffData_"+paramInfo.TableName;
                    if (compareResult.Rows.Count > 0)
                    {
                        if (m_DifferentDataTables == null) m_DifferentDataTables = new List<DataTable>();
                        m_DifferentDataTables.Add(compareResult);
                    }
                }
            }
        }

        public List<RpoAmount> RunTestCases()
        {
            var failCaseAmountReportObjs = new List<RpoAmount>();
            try
            {
                if (string.IsNullOrEmpty(m_TestCaseDirPath) || !Directory.Exists(m_TestCaseDirPath))
                {
                    throw new ArgumentException("没有待测试的相关文件");
                }
                string[] dirs = Directory.GetDirectories(m_TestCaseDirPath);
                CaseTotalAmount = dirs.Length;
                foreach (string caseDirPath in dirs)
                {
                    var rpoAmount = RunEachTestCase(caseDirPath);
                    if (rpoAmount != null) failCaseAmountReportObjs.Add(rpoAmount);
                }
            }
            catch (Exception ex)
            {
                TextOutputHelper.OutputExceptionTextFile(m_TestCaseDirPath + "\\" + FN_EXPECT_DATA + ".txt",ex);
            }
            if (failCaseAmountReportObjs.Count > 0)
                OutputTestResultInfoToTextFile(m_TestCaseDirPath + "\\" + FN_FAIL_REPORT + ".txt", failCaseAmountReportObjs);
            return failCaseAmountReportObjs;
        }

        protected RpoAmount RunEachTestCase(string caseDirPath)
        {
            RpoAmount reVal=null;
            
            try
            {
                string sourceDataPath = caseDirPath + "\\" + FN_SOURCE_DATA + ".xls";
                if (File.Exists(sourceDataPath))
                {
                    var excelHlp = new ExcelHelper(sourceDataPath);
                    InitSourceData(excelHlp);
                    ExecProecss();
                    CompareExpectDatas(caseDirPath);
                    if (m_DifferentDataTables != null && m_DifferentDataTables.Count > 0)
                    {
                        var diffDataPath = caseDirPath + "\\" + FN_DIFFERENT_DATA + ".xls";
                        excelHlp.OutputExcel(diffDataPath, m_DifferentDataTables);
                        reVal = new RpoAmount
                        {
                            CaseDirPath = caseDirPath,
                            FailInnerTableAmount = m_DifferentDataTables.Count
                        };
                    }
                }
            }
            catch (Exception ex)
            {
                TextOutputHelper.OutputExceptionTextFile(caseDirPath + "\\" + FN_EXPECT_DATA + ".txt", ex);
            }
            return reVal;
        }

        protected void OutputTestResultInfoToTextFile(string filePath,List<RpoAmount> objs)
        {
            if (objs == null || objs.Count == 0) return;
            var sbInfoContext = new StringBuilder();
            foreach(var r in objs)
            {
                sbInfoContext.Append("Fail Case : DiffTableAmount=["+r.FailInnerTableAmount+"]; CaseDirPath=["+r.CaseDirPath+"]");
                sbInfoContext.Append("\r\n\r\n");
            }
            if(sbInfoContext.Length> 0)
                TextOutputHelper.OutputTextFile(filePath, sbInfoContext.ToString());
        }

        public abstract void ExecProecss();
    }
}